package com.sc.nft.task;

import cn.hutool.core.collection.CollectionUtil;
import com.sc.nft.entity.WantBuyOrder;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalException;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.WantBuyOrderService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author 刘国航
 * @desc
 * @since 2024/12/21 16:21
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class WantBuyOrderTask {

    private final WantBuyOrderService wantBuyOrderService;
    private final RedissonClient redissonClient;
    private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

    /**
     * 关闭求购单
     */
    @XxlJob("closeWantBuyOrder")
    public void closeWantBuyOrder() {
        List<WantBuyOrder> wantBuyOrderList = wantBuyOrderService.queryReleasesFiveMinuteLater();
        if (CollectionUtil.isEmpty(wantBuyOrderList)) {
            return;
        }
        wantBuyOrderList.forEach(wantBuyOrder -> {
            executor.schedule(() -> {
                RLock lock = redissonClient.getLock(RedisKeyEnum.WANT_BUY_ORDER.getKey() + wantBuyOrder.getId());
                try {
                    boolean res = lock.tryLock(30, 30, TimeUnit.SECONDS);
                    if (!res) {
                        throw new GlobalException("操作频繁，请重试！！！！");
                    }
                    wantBuyOrderService.close(wantBuyOrder.getId());
                } catch (Exception e) {
                    throw new GlobalRunTimeException(e.getMessage());
                } finally {
                    if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                        lock.unlock();
                    }
                }
            }, calculateDelayInSeconds(wantBuyOrder.getEndTime()), TimeUnit.SECONDS);
        });
    }

    private long calculateDelayInSeconds(Date schedulePushTime) {
        return Math.max((schedulePushTime.getTime() - System.currentTimeMillis()) / 1000, 1L); // 转换为秒
    }

}
